{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Execute "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The last step of the quantum algorithm development process with Classiq is to execute the quantum program on a quantum computer or a simulator. This can be done in the IDE or through the Python SDK. Classiq offers access to a wide variety of quantum computers with different hardware modalities from several companies including: IonQ, Quantinuum, IBM, OQC and Rigetti, as well as to several simulators.\n",
    "\n",
    "The execution phase is composed of configuration and access to the results. In the following, we cover these parts through a concrete example. First we start with the default execution options of Classiq, the execution we have encountered in previous example of this 101 guide."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Default Execution"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Continuing with the algorithm from previous chapters, we want to create a quantum algorithm that calculates in a superposition the arithmetic expression $y=x^2+1$. The following algorithm written in Qmod implements the desired task:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:23.008088Z",
     "iopub.status.busy": "2024-05-07T13:27:23.007622Z",
     "iopub.status.idle": "2024-05-07T13:27:25.811325Z",
     "shell.execute_reply": "2024-05-07T13:27:25.810608Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import *\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def main(x: Output[QNum], y: Output[QNum]):\n",
    "\n",
    "    allocate(4, x)\n",
    "    hadamard_transform(x)  # creates a uniform superposition\n",
    "    y |= x**2 + 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And the algorithm can then be synthesized:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:25.816813Z",
     "iopub.status.busy": "2024-05-07T13:27:25.815389Z",
     "iopub.status.idle": "2024-05-07T13:27:28.337602Z",
     "shell.execute_reply": "2024-05-07T13:27:28.336648Z"
    }
   },
   "outputs": [],
   "source": [
    "quantum_program = synthesize(create_model(main))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div  style=\"text-align:center;\">\n",
    "    <img src=\"https://docs.classiq.io/resources/design.gif\">\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The quantum program at hand can now be executed directly and the results can be analyzed:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:28.346633Z",
     "iopub.status.busy": "2024-05-07T13:27:28.345427Z",
     "iopub.status.idle": "2024-05-07T13:27:30.814986Z",
     "shell.execute_reply": "2024-05-07T13:27:30.814315Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'x': 0.0, 'y': 1.0}: 91, {'x': 5.0, 'y': 26.0}: 72, {'x': 10.0, 'y': 101.0}: 71, {'x': 2.0, 'y': 5.0}: 71, {'x': 15.0, 'y': 226.0}: 68, {'x': 14.0, 'y': 197.0}: 67, {'x': 12.0, 'y': 145.0}: 66, {'x': 11.0, 'y': 122.0}: 64, {'x': 9.0, 'y': 82.0}: 61, {'x': 1.0, 'y': 2.0}: 60, {'x': 13.0, 'y': 170.0}: 60, {'x': 4.0, 'y': 17.0}: 59, {'x': 6.0, 'y': 37.0}: 49, {'x': 8.0, 'y': 65.0}: 47, {'x': 3.0, 'y': 10.0}: 47, {'x': 7.0, 'y': 50.0}: 47]\n"
     ]
    }
   ],
   "source": [
    "job = execute(quantum_program)\n",
    "results = job.result()[0].value.parsed_counts\n",
    "print(results)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div  style=\"text-align:center;\">\n",
    "    <img src=\"https://docs.classiq.io/resources/execution.gif\">\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The above demonstrates how the execution can be done with the default configuration of Classiq which is an execution on a simulator (with up to 25 qubits) with 1000 shots. Let's see how we can execute with other configurations."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Configuring the Execution "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Configuration in the IDE"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "From the IDE, the execution configuration is done via the `Execution` tab, which is automatically accesses when the `Execute` button is pressed from the visualization of the quantum program:\n",
    "<div  style=\"text-align:center;\">\n",
    "    <img src=\"https://docs.classiq.io/resources/execution_configuration.png\">\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "On the left-hand side one can see a list of all the available simulators that can be accessed. On the top part, one can tick the `Hardware` box to see a lost of all the available hardwares one can access via the platform. The hardwares as well as some of the simulators require further credentials that needs to be entered once the `Run` button is pressed. These credentials are the vendor's credentials for accessing the relevant compute resources (more details can be found in the reference manual).\n",
    "\n",
    "On the right-hand side of the screen, one can configure the specific execution. The `Num Shots` can be used to change the number of shots the quantum program will be sampled, and one can enter an indicative `Job Name`. The `Random Seed` can be used in order to receive the exact same results when a simulator is used (as well as for more advanced execution options on real hardware such as variational quantum algorithms and advanced transpilation methods).\n",
    "\n",
    "After the configuration is done, all that remains is to press to `Run` button."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Configuration in the SDK"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One can change the execution configuration from the SDK as well. This is done by adapting the quantum model with the desired execution preferences, similarly to the constraints and preferences from the optimization phase. \n",
    "\n",
    "The following code demonstrates how to change the number of shots, to set a name for the job and to set a random seed for the simulator:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:30.852205Z",
     "iopub.status.busy": "2024-05-07T13:27:30.851656Z",
     "iopub.status.idle": "2024-05-07T13:27:30.860578Z",
     "shell.execute_reply": "2024-05-07T13:27:30.859960Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq.execution import ExecutionPreferences\n",
    "\n",
    "quantum_model = create_model(main)\n",
    "quantum_model_with_execution_preferences = set_execution_preferences(\n",
    "    quantum_model,\n",
    "    ExecutionPreferences(\n",
    "        num_shots=2048, job_name=\"classiq 101 - execute\", random_seed=767\n",
    "    ),\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And then the adapted quantum model can be synthesized and executed:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:30.863189Z",
     "iopub.status.busy": "2024-05-07T13:27:30.862693Z",
     "iopub.status.idle": "2024-05-07T13:27:33.184810Z",
     "shell.execute_reply": "2024-05-07T13:27:33.183874Z"
    }
   },
   "outputs": [],
   "source": [
    "quantum_program_with_execution_preferences = synthesize(\n",
    "    quantum_model_with_execution_preferences\n",
    ")\n",
    "job = execute(quantum_program_with_execution_preferences)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The full list of configuration options for the execution preferences can be found in the reference manual."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Accessing the Results"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Results in the IDE"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once you press the `Run` button from the `Execution` tab you will automatically be transitioned to the `Jobs` tab of the platform. All your jobs are listed on the left-hand side, and by clicking on a specific job, its information is depicted below the job name.\n",
    "\n",
    "<div  style=\"text-align:center;\">\n",
    "    <img src=\"https://docs.classiq.io/resources/execution_job_ide.png\">\n",
    "</div>\n",
    "\n",
    "On the right-hand side, the histogram of the results is depicted. Each bin represent a specific measurement result and its hight represents the counts of that measurement. By hovering over a specific bin, the variables of that measurement results are depicted, as well as the counts of that bin.\n",
    "\n",
    "At the top-right corner there are two buttons. The right one allows downloading the results of the job in a specific format like `.csv`, and the left button enables further options for analyzing the histogram results."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Results in the SDK"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `job` variable which is the output of the `execute` command contains all the data about the execution job. Some of the meta data can be accessed directly from this object:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:33.190235Z",
     "iopub.status.busy": "2024-05-07T13:27:33.188740Z",
     "iopub.status.idle": "2024-05-07T13:27:33.196061Z",
     "shell.execute_reply": "2024-05-07T13:27:33.195392Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The job on the provider Classiq on the backend simulator with 2048 shots is QUEUED can be accessed in the IDE with this URL: https://platform.classiq.io/jobs/ea0fa2c8-515a-48cf-b8ce-c5e6f6c74803\n"
     ]
    }
   ],
   "source": [
    "print(\n",
    "    f\"The job on the provider {job.provider} on the backend {job.backend_name} with {job.num_shots} shots is {job.status} can be accessed in the IDE with this URL: {job.ide_url}\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In addition to the meta data, we see the option to open the job also in the IDE. This can be done directly with:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:33.200851Z",
     "iopub.status.busy": "2024-05-07T13:27:33.199653Z",
     "iopub.status.idle": "2024-05-07T13:27:33.205566Z",
     "shell.execute_reply": "2024-05-07T13:27:33.204861Z"
    }
   },
   "outputs": [],
   "source": [
    "job.open_in_ide()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The actual results of the job can be accessed with:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:33.210233Z",
     "iopub.status.busy": "2024-05-07T13:27:33.209026Z",
     "iopub.status.idle": "2024-05-07T13:27:34.392765Z",
     "shell.execute_reply": "2024-05-07T13:27:34.392157Z"
    }
   },
   "outputs": [],
   "source": [
    "results = job.result()[0].value"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `results` variable contains a dictionary of the measured variables of our algorithm and their respective counts:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:34.395555Z",
     "iopub.status.busy": "2024-05-07T13:27:34.395055Z",
     "iopub.status.idle": "2024-05-07T13:27:34.398938Z",
     "shell.execute_reply": "2024-05-07T13:27:34.398347Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'x': 6.0, 'y': 37.0}: 146, {'x': 3.0, 'y': 10.0}: 143, {'x': 12.0, 'y': 145.0}: 141, {'x': 9.0, 'y': 82.0}: 137, {'x': 15.0, 'y': 226.0}: 134, {'x': 13.0, 'y': 170.0}: 133, {'x': 14.0, 'y': 197.0}: 133, {'x': 2.0, 'y': 5.0}: 133, {'x': 7.0, 'y': 50.0}: 129, {'x': 11.0, 'y': 122.0}: 128, {'x': 10.0, 'y': 101.0}: 126, {'x': 1.0, 'y': 2.0}: 123, {'x': 4.0, 'y': 17.0}: 117, {'x': 8.0, 'y': 65.0}: 115, {'x': 5.0, 'y': 26.0}: 111, {'x': 0.0, 'y': 1.0}: 99]\n"
     ]
    }
   ],
   "source": [
    "print(results.parsed_counts)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The raw bit strings can also be accessed directly with:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:34.401373Z",
     "iopub.status.busy": "2024-05-07T13:27:34.400898Z",
     "iopub.status.idle": "2024-05-07T13:27:34.404274Z",
     "shell.execute_reply": "2024-05-07T13:27:34.403600Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'000000100001': 123, '010100101001': 137, '000100010100': 117, '111000101111': 134, '000000010000': 99, '001100100111': 129, '000010100011': 143, '101010101101': 133, '000110100101': 111, '010000011000': 115, '001001010110': 146, '011110101011': 128, '100100011100': 141, '110001011110': 133, '000001010010': 133, '011001011010': 126}\n"
     ]
    }
   ],
   "source": [
    "print(results.counts)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And the direct mapping between the bit strings and the measured variables can aldo be extracted: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:34.406341Z",
     "iopub.status.busy": "2024-05-07T13:27:34.406176Z",
     "iopub.status.idle": "2024-05-07T13:27:34.409451Z",
     "shell.execute_reply": "2024-05-07T13:27:34.408768Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'000000100001': {'x': 1.0, 'y': 2.0}, '010100101001': {'x': 9.0, 'y': 82.0}, '000100010100': {'x': 4.0, 'y': 17.0}, '111000101111': {'x': 15.0, 'y': 226.0}, '000000010000': {'x': 0.0, 'y': 1.0}, '001100100111': {'x': 7.0, 'y': 50.0}, '000010100011': {'x': 3.0, 'y': 10.0}, '101010101101': {'x': 13.0, 'y': 170.0}, '000110100101': {'x': 5.0, 'y': 26.0}, '010000011000': {'x': 8.0, 'y': 65.0}, '001001010110': {'x': 6.0, 'y': 37.0}, '011110101011': {'x': 11.0, 'y': 122.0}, '100100011100': {'x': 12.0, 'y': 145.0}, '110001011110': {'x': 14.0, 'y': 197.0}, '000001010010': {'x': 2.0, 'y': 5.0}, '011001011010': {'x': 10.0, 'y': 101.0}}\n"
     ]
    }
   ],
   "source": [
    "print(results.parsed_states)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The notation of wether the bit strings are interpreted with the least significant bit (LSB) on the right or on the left can also be extracted:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:34.411732Z",
     "iopub.status.busy": "2024-05-07T13:27:34.411295Z",
     "iopub.status.idle": "2024-05-07T13:27:34.414738Z",
     "shell.execute_reply": "2024-05-07T13:27:34.414062Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "print(results.counts_lsb_right)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "All the above should enable one to analyze the results and post-process them in Python as needed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:27:34.416795Z",
     "iopub.status.busy": "2024-05-07T13:27:34.416627Z",
     "iopub.status.idle": "2024-05-07T13:27:34.426203Z",
     "shell.execute_reply": "2024-05-07T13:27:34.425633Z"
    }
   },
   "outputs": [],
   "source": [
    "write_qmod(quantum_model_with_execution_preferences, \"execute\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.11.7 ('classiq')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  },
  "vscode": {
   "interpreter": {
    "hash": "529b62266d4f537a408698cf820854c65fe877011c7661f0f70aa11c4383fddc"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
